
  #include "data.h"


  /******************************************************************
    Dichiarazione delle variabili e delle funzioni interne al file.
  ******************************************************************/
  
  class Data data;
  
  /******************************************************************
    Dichiarazione delle variabili e delle funzioni esterne al file.
  ******************************************************************/
     
  
  /*
  ----------------- procedura Data ----------------------------------------
  *** Scritta il: 19/12/03
  E' la costruttrice della classe. Si effettuano alcune inizializzazioni.     
  *** Ultima modifica:
  */   
  Data::Data()
  {
     int i;
     
     
     /* Si inizializzano i nomi dei file che contengono dati con quelli di 
        default. */  
     
     // file dei dati      
     strcpy(data_file_name, DEFAULT_DATA_FILE);
     
     // train set
     strcpy(train_file_name, DEFAULT_TRAIN_FILE);
     
     // test set 
     strcpy(test_file_name, DEFAULT_TEST_FILE);
     
     // Si inizializza il tipo di distanza di default.
     dist_type = 2.0;
     
     // Per default si  considerano valide tutte le features.
     for (i=0; i < MAX_FEATURES; ++i)
        valid_features[i] = true; 
     
     // Si inizializzano i ranges con dei valori non validi
     for (i=0; i < MAX_FEATURES; ++i)
     { 
        train_ranges[i].avg = NULL_VALUE;
        test_ranges[i].avg = NULL_VALUE;
        
        train_ranges[i].dev = -1.0;
        test_ranges[i].dev = -1.0;
     } 
     
     // Inizializzazione del formato dei dati.
     special_format = false;
     char_format = false;
     
         
     return;  
  }
  
   /*
  ----------------- procedura give_data_name -----------------------------
  *** Scritta il: 19/12/03
  Restituisce il nome del file che contiene i dati.
  *** Ultima modifica:
  */   
  inline string Data::give_data_name()
  {  
       // Si costruisce una stringa che contiene il nome del data set.
      string tmp_string(data_file_name);      
      
      
      return tmp_string;
  }  
  
  /*
  ----------------- procedura give_train_name -----------------------------
  *** Scritta il: 19/12/03
  Restituisce il nome del file che contiene il  train set.
  *** Ultima modifica:
  */   
  inline string Data::give_train_name()
  {  
       // Si costruisce una stringa che contiene il nome del train set.
      string tmp_string(train_file_name);      
      
      
      return tmp_string;
  }  
  
  /*
  ----------------- procedura give_test_name ------------------------------
  *** Scritta il: 19/12/03
  Restituisce il nome del file che contiene il  train set.
  *** Ultima modifica:
  */   
  inline string Data::give_test_name()
  {  
      // Si costruisce una stringa che contiene il nome del test set.
      string tmp_string(test_file_name);      
      
      
      return tmp_string;
  }
  
  /*
  ----------------- procedura give_classes_num ----------------------------
  *** Scritta il: 19/12/03
  Restituisce il numero di classi effettive del problema.
  *** Ultima modifica:
  */   
  int Data::give_classes_num()
  {  
           
            
      return classes_num;
  }

  /*
  ----------------- procedura give_train_item -----------------------------
  *** Scritta il: 19/12/03
  Restituisce un item del train set scelto in maniera random.
  *** Ultima modifica:
  */   
  void Data::give_train_item(double *vec)  
  {  
      int item_num, i;
      
       
      // Si sceglie un item del train set in maniera casuale.
      item_num = rnd(0, train_num - 1);
      
      // Si copia l'item scelto nel vettore passato come parametro.
      for(i=0; i < features_num; ++i)
         vec[i] = train_set[item_num].vector[i];
      
      return;
  }
  
  /*
  ----------------- procedura give_train_item -----------------------------
  *** Scritta il: 19/12/03
  Restituisce nel parametro vec l'item del train set di indice index. 
  *** Ultima modifica:
  */   
  void Data::give_train_item(double vec[], int index)  
  {  
      int item_num, i;
      
       
           
      // Si copia l'item chiesto nel vettore passato come parametro.
      for(i=0; i < features_num; ++i)
         vec[i] = train_set[index].vector[i];
      
      return;
  }    
  
  /*
  ----------------- procedura show_train_item -----------------------------
  *** Scritta il: 19/12/03
  Visualizza l'item del train set di indice index, nello stream passato co-
  me parametro. 
  *** Ultima modifica:
  */   
  void Data::show_train_item(ostream *out_stream, int index)  
  {  
       int i;
      
     /* *out_stream<<endl<<"digitare l'indice dell'item del train"
              " set che si vuole visualizzare (si parte da 1): ";
      cin>>index;
      
      index--; */
      
      //*out_stream<<endl<<index+1<<"-simo item del train set:"<<endl;
      *out_stream<<endl<<"c: "<<train_set[index].cluster;
      *out_stream<<" v: ";
      
      // Si visualizza il vettore.
      for(i=0; i < features_num; ++i)
         if (valid_feature(i))
           *out_stream<<train_set[index].vector[i]<<" ";
    
    
      return;
  }
  /*
  ----------------- procedura show_test_item -----------------------------
  *** Scritta il: 19/12/03
  Visualizza l'item del train set di indice index, nello stream passato co-
  me parametro. 
  *** Ultima modifica:
  */   
  void Data::show_test_item(ostream *out_stream, int index)  
  {  
      int i;
      
     /* *out_stream<<endl<<"digitare l'indice dell'item del train"
              " set che si vuole visualizzare (si parte da 1): ";
      cin>>index;
      
      index--; */
      
      //*out_stream<<endl<<index+1<<"-simo item del train set:"<<endl;
      *out_stream<<endl<<"c: "<<test_set[index].cluster;
      *out_stream<<" v: ";
      
      // Si visualizza il vettore.
      for(i=0; i < features_num; ++i)
         if (valid_feature(i))
           *out_stream<<test_set[index].vector[i]<<" ";
    
    
      return;
  }
  
  /*
  ----------------- procedura give_features_num ---------------------------
  *** Scritta il: 19/12/03
  Restituisce il numeri di features del problema. 
  *** Ultima modifica:
  */   
  int Data::give_features_num()
  {  
      
      return features_num;
  }    
  
  /*
  ----------------- procedura give_train_num ------------------------------
  *** Scritta il: 19/12/03
  Restituisce il numeri di items del train set.
  *** Ultima modifica:
  */   
  int Data::give_train_num()
  {  
      
      return train_num;
  }    
  
  /*
  ----------------- procedura give_dist_type ------------------------------
  *** Scritta il: 19/12/03
  Restituisce il tipo di distanza utilizzata.
  *** Ultima modifica:
  */   
  double Data::give_dist_type()
  {  
      
      return dist_type;
  }    
  /*
  ----------------- procedura give_test_num -------------------------------
  *** Scritta il: 19/12/03
  Restituisce il numeri di items del test set.
  *** Ultima modifica:
  */   
  int Data::give_test_num() 
  {  
      
      if (test)
        return test_num; 
      else abort_message("ERRORE!: test set ASSENTE!");  
  }
  
  /*
  ----------------- procedura give_train_range ----------------------------
  *** Scritta il: 19/12/03
  Restituisce il valore dev dell'elemento di indice index del vettore ran-
  ges del train set.
  *** Ultima modifica:
  */   
  double Data::give_train_range(int index) 
  {  
      
     
       return train_ranges[index].dev; 
  }
  
  /*
  ----------------- procedura give_train_aver -----------------------------
  *** Scritta il: 19/12/03
  Restituisce il valore avg dell'elemento di indice index del vettore ran-
  ges del train set.
  *** Ultima modifica:
  */   
  double Data::give_train_aver(int index) 
  {  
      
     
       return train_ranges[index].avg; 
  }
  
  /*
  ----------------- procedura give_test_range -----------------------------
  *** Scritta il: 19/12/03
  Restituisce il valore dev dell'elemento di indice index del vettore ran-
  ges del test set.
  *** Ultima modifica:
  */   
  double Data::give_test_range(int index) 
  {  
      
     
       return test_ranges[index].dev; 
  }
  
  /*
  ----------------- procedura give_test_aver -----------------------------------
  *** Scritta il: 19/12/03
  Restituisce il valore avg dell'elemento di indice index del vettore ran-
  ges del test set.
  *** Ultima modifica:
  */   
  double Data::give_test_aver(int index) 
  {  
      
     
       return test_ranges[index].avg; 
  }
  
  /*
  ----------------- procedura get_params ---------------------------------
  *** Scritta il: 19/12/03
  Carica i parametri relativi ai dati del problema. Il nome del file che 
  contiene le informazioni puo', eventualmente, essere letto dalal riga di
  comando passata come  parametro.  Il terzo parametro specifica se visua-
  lizzare un messzaggio oppure no.
  *** Ultima modifica:
  */
  void Data::get_params(int argc, char *argv[], bool visual)
  {
     ifstream in_stream; 	  
     char line[MAX_CHAR_LINE], *line_ptr;
     int i,params;
     char tmp_name[MAX_CHAR_FILE_NAME];
          

     // Si verifica la riga di comando per comprendere quale file aprire.
     if (read_param(argc, argv, "-d", tmp_name))
       /* Si aggiorna il nome del file dei dati con quello passato dall'ut-
          ente alla riga di comando. */
       strcpy(data_file_name, tmp_name);   
  
     // Si apre il file che contiene i dati da leggere.
     in_stream.open(data_file_name);
    
       
           
     // Si controlla se il file e' stato aperto correttamente.
     if (!in_stream)
       abort_message("Impossibile aprire il file \"%s\" \n \
       per la lettura dei parametri!", data_file_name);     
     
     
     /* Prima si acquisisce il numero di parametri presenti nel file.
     get_line(line, &in_stream, MAX_CHAR_LINE);

     if (!get_int(line, "N_PARAMS", N_params))
       /* Se non si riesce ad acquisire il numero di paarmetri, il program-
          ma viene terminato. 
       abort_message("ERRORE ! Impossibile trovare \"N_PARAMS\" nel\
        file %s",data_file_name);


     /* Il ciclo che segue legge da file tutti i parametri dell'evo-
        luzione. */
     params = 0;
     
     
     while (get_line(line, &in_stream, MAX_CHAR_LINE))  /*&& 
            (params < N_params))*/
     {        
        if (extract_param(line))
          ++params;
        else abort_message("ERRORE durante la lettura del file %s",
                            data_file_name);
     }
     if (params < N_params)
       abort_message("Il numero di parametri contenuto nel file %s e' \
       insufficiente", data_file_name);
     
     // Si chiude il file.
     in_stream.close();
     
     // Si visualizza un messaggio.
     if (visual)
       cout<<endl<<endl<<"I parametri dei dati sono stati letti dal \
       file: "<<data_file_name<<endl;
       
     /******** Dopo l'acquisizione dei parametri si costruiscono ********
      ******** gli array e si caricano i dati dai file.          ********/
    
     
     if (all) {
       load_data();       
       //build_sets(); //vengono costruiti da init_run!
     }  
     else {
       // Si costruisce il train set     
       load_train_set();
       // Si controlla se c'e' il test set.     
       if (test)
         load_test_set();
     }  
     
     
     // Si effettua la normalizzazione dei data set.
     normalize(); 
    
     
     cout<<endl<<"ATTENZIONE!: i data  set sono stati normalizzati!"<<endl;
     
     
     return;
  }
  
  /*
  ----------------- Procedura extract_param -----------------------------
  *** Scritta il:
  Estrae dalla linea in input il parametro contenuto e lo assegna al re-
  lativo attributo.
  *** Ultima modifica: ore 16.00 del 04/04/03
  */
  bool Data::extract_param(char *line)
  {
     char *line_ptr;     

     /* Si convertono i minuscolo tutti i caratteri presenti nella linea
        passata come parametro. */
     str_lwr(line, MAX_CHAR_LINE);
     

     // ***************** Numero di classi effettive **********************
     if (strstr(line, "n_classes"))
       if (get_int(line, "n_classes", classes_num))
          return true;
       else abort_message("ERRORE ! Nella lettura del parametro \
		       \"N_classes\"!");
     
     // ***************** Numero di features ******************************
     if (strstr(line, "n_features"))
       if (get_int(line, "n_features", features_num))
          return true;
       else abort_message("ERRORE ! Nella lettura del parametro \
		       \"N_features\"!");
     
     // ************ Numero di items del train set ************************
     if (strstr(line, "n_train"))
       if (get_int(line, "n_train", train_num))       
          return true;          
       else abort_message("ERRORE ! Nella lettura del parametro \
		       \"N_train\"!");
     
     // ************ Numero di items del test set ************************
     if (strstr(line, "n_test"))
       if (get_int(line, "n_test", test_num))
       {
          test = true;
                               
          return true;
       }    
       else abort_message("ERRORE ! Nella lettura del parametro \
		       \"N_test\"!");
       
     // ************ Numero di items del data set TOTALE *****************
     if (strstr(line, "n_data"))
       if (get_int(line, "n_data", data_num))
       {       
                               
          return true;
       }    
       else abort_message("ERRORE ! Nella lettura del parametro \
		       \"N_data\"!");  
       
          
     // ************ Nome del file del train set **************************
     if (strstr(line, "train_name"))
     {
       if (get_string(line, "train_name", line_ptr))
       {                                             
          strcpy(train_file_name, line_ptr);
                     
          return true;
       }                  
       else abort_message("ERRORE ! Nella lettura del parametro \
		       \"train_name\"!");  
     }
     // ************ Nome del file del data set **************************
     if (strstr(line, "data_name"))
     { 
       if (get_string(line, "data_name", line_ptr))
       {                                             
          strcpy(data_set_name, line_ptr);
	  
	  all = test = true;
                     
          return true;
       }                  
       else abort_message("ERRORE ! Nella lettura del parametro \
		       \"data_name\"!");  
     }
     
     // ************ Percenutale di items del train set ************************
     if (strstr(line, "p_train"))
       if (get_double(line, "p_train", train_per))       
          return true;          
       else abort_message("ERRORE ! Nella lettura del parametro \
		       \"p_train\"!");    
       
     // ************ Nome del file del test set ***************************
     if (strstr(line, "test_name"))
     {      
       if (get_string(line, "test_name", line_ptr))
       {
         strcpy(test_file_name, line_ptr);
         
         return true;
       }      
       else abort_message("ERRORE ! Nella lettura del parametro \
	  	       \"test_name\"!");        
     }  
       
     // ************ Tipo di distanza *************************************
     if (strstr(line, "dist_type"))
       if (get_double(line, "dist_type", dist_type))
         return true;
       else abort_message("ERRORE ! Nella lettura del parametro \
		       \"dist_type\"!");  
         
     // ************ Acquisizione delle features non valide ***************
     if (strstr(line, "no_features"))
     {
        // Si acquisicono le features non valide.
        get_no_features(line_ptr);
         
        return true;
     }      
             
     // ************ Formato dei dati ************************************
     if (strstr(line, "special"))
        return special_format = true;
     if (strstr(line, "char"))
        return char_format  = true; 
               
     abort_message("ERRORE ! Nella lettura dei parametri dei dati! \
		           Questa linea e' sbagliata: %s\n", line);
  }
  
  /*
  ----------------- Procedura give_params ---------------------------------
  *** Scritta il:
  Copia nel file passato come parametro quello che contiene i parametri.
  *** Ultima modifica: 
  */
  void Data::give_params(ofstream *out_stream)
  {
     ifstream tmp_stream(data_file_name); 
  
      

     // Si controlla la corretta apertura del file.
     if (!tmp_stream)
       *out_stream<<(char *) "\nATTENZIONE\nImpossibile aprire il file: "<<
                      data_file_name;

     // Si memorizzano i parametri evolutivi.
     file_copy(&tmp_stream, out_stream);

     // Si chiude il file aperto.
     //delete tmp_stream;
     
     
     return;
 }    



      
 
  /*
  ----------------- procedura load_train_set -------------------------------
  *** Scritta il: 19/12/03
  Costruisce dinamicamente l'array che deve contenere il train set e lo ca-
  rica dal file.
  *** Ultima modifica:
  */ 

  void Data::load_train_set()
  {
     int i,j, trash, tmp_features, index;
     ifstream in_stream; 

 
     // Si costruisce il vettore che deve contenere i data item.     
     train_set = new data_item[train_num];
          
     // Si apre il file che contiene il train set
     in_stream.open(train_file_name);
        
     // Si controlla se il file e' stato aperto correttamente.
     if (!in_stream) //.open(file_name))
       abort_message("imossibile aprire il file: \"%s\" \n\
       per la lettura del train set!", train_file_name);
       
     /* Si controlla se bisogna caricare il formato di dati speciale o 
        quello standard.  */
     if (special_format)
       load_data_set(&in_stream, train_set, train_num);
     else load_data_set2(&in_stream, train_set, train_num);  

     /* Ciclo principale per la memorizzazione del numero di items specifi-
        cato dal parametro items_num.  v
     for (i=0; i < train_num; ++i) 
     {
        // *** Inizializzazione dell'i-esimo item del data set. ***
        train_set[i].cluster = -1;
      
        for (j=0; j < features_num; j++)
	       train_set[i].vector[j]= ZERO_VALUE;

        // *** Memorizzazione dei dati relativi all'i-esimo item. ***
        
           // Si evita il primo elemento della riga.
           in_stream>>trash;
        
           // Si memorizza il cluster vero dell'item.
           in_stream>>train_set[i].cluster;
         ++train_set[i].cluster; // prova VALE SOLO PER I CARATTERI !!!!
 
           // Si memorizza il numero di feaures presenti sulla riga.
           in_stream>>tmp_features; 
             
            
           // Memorizzazione delle features
           for (j=0; j < tmp_features; ++j)              
          {
              // Si memorizza l'indice della feature.
             in_stream>>index;
          
            
              // Si controlla se l'indice e' valido.
              if ((index >= 0) && (index < MAX_FEATURES)) 
                in_stream>>train_set[i].vector[index];
           //  in_stream>>train_set[i].vector[j];
            // else abort_message("ATTENZIONE! Il file %s contiene una features\
            // non valida alla riga %d %d", train_file_name, i, index);           
          }          
     }  */
      
     // Si calcolano i ranges delle features.
     comp_train_ranges();
     
     // Si calcola la distribuzione delle classi
     comp_dist_train();
 

     return;
  }
  
  /*
  ----------------- procedura comp_dist_train -----------------------------------
  *** Scritta il: 19/12/03
  calcola la distribuzione delle classi del train set.
  *** Ultima modifica:
  */ 
  void Data::comp_dist_train()
  {
    int i;
    data_item tmp_item;
    
    for (i=0; i < MAX_CLASSES; ++i)
       dist_train[i] = 0;
    
    for (i=0; i < give_train_num(); ++i) {
       tmp_item = train_set[i];
       dist_train[tmp_item.cluster]++;       
    }
       
    return;
  }
  
  /*
  ----------------- procedura load_data -----------------------------------
  *** Scritta il: 19/12/03
  Costruisce dinamicamente l'array che deve contenere il train set e lo ca-
  rica dal file.
  *** Ultima modifica:
  */ 
  void Data::load_data()
  {
     int i,j, trash, tmp_features, index;
     ifstream in_stream;
     
     
     if (data_num == 0)
       abort_message("ERRORE!: data_num = 0!!!");
     
     
     
     // Si calcolano dimensioni di train e test set.
     train_num = train_per * data_num;
     test_num  = data_num  - train_num;
     
     
          
     // Si costruiscono i vettori che devono contenere i data items.     
     data_set  = new data_item[data_num];
     train_set = new data_item[train_num];
     test_set  = new data_item[test_num];
        
           
     // Si apre il file che contiene il data set totale
     in_stream.open(data_set_name);
        
     // Si controlla se il file e' stato aperto correttamente.
     if (!in_stream) //.open(file_name))
       abort_message("imossibile aprire il file: \"%s\" \n\
       per la lettura del data set!", data_set_name);
       
     /* Si controlla se bisogna caricare il formato di dati speciale o 
        quello standard.  */
     if (special_format)
       load_data_set(&in_stream, data_set, data_num);
     else load_data_set2(&in_stream, data_set, data_num);

     /* Ciclo principale per la memorizzazione del numero di items specifi-
        cato dal parametro items_num.  v
     for (i=0; i < train_num; ++i) 
     {
        // *** Inizializzazione dell'i-esimo item del data set. ***
        train_set[i].cluster = -1;
      
        for (j=0; j < features_num; j++)
	       train_set[i].vector[j]= ZERO_VALUE;

        // *** Memorizzazione dei dati relativi all'i-esimo item. ***
        
           // Si evita il primo elemento della riga.
           in_stream>>trash;
        
           // Si memorizza il cluster vero dell'item.
           in_stream>>train_set[i].cluster;
         ++train_set[i].cluster; // prova VALE SOLO PER I CARATTERI !!!!
 
           // Si memorizza il numero di feaures presenti sulla riga.
           in_stream>>tmp_features; 
             
            
           // Memorizzazione delle features
           for (j=0; j < tmp_features; ++j)              
          {
              // Si memorizza l'indice della feature.
             in_stream>>index;
          
            
              // Si controlla se l'indice e' valido.
              if ((index >= 0) && (index < MAX_FEATURES)) 
                in_stream>>train_set[i].vector[index];
           //  in_stream>>train_set[i].vector[j];
            // else abort_message("ATTENZIONE! Il file %s contiene una features\
            // non valida alla riga %d %d", train_file_name, i, index);           
          }          
     }  */
      
     // Si calcolano i ranges delle features.
     //comp_train_ranges();
 

     return;
  }
  
  /*
  ----------------- procedura build_sets -------------------------------
  *** Scritta il: 19/12/03
  Costruisce dinamicamente l'array che deve contenere il train set e lo ca-
  rica dal file.
  *** Ultima modifica:
  */ 

  void Data::build_sets()
  {
    list<int> rnd_list;
    list<int>::iterator rnd_iter;
    int i, tmp, rnd_ptr;
    
    
    // Generazione di una lista di interi.  
    for (i=0; i < data_num; ++i)
       rnd_list.push_back(i);
    
         
    // COSTRUZIONE TRAIN SET  
    for(i=0; i < train_num; ++i)        
    {  // *************** VERSIONE STANDARD *****************************
       /* Si sceglie in maniera casuale un elemento della lista di inizi-
          alzzazione. */
       rnd_ptr = rnd(0, rnd_list.size() - 1); 
       
       // Si punta l'elemento da inizializzare.
       rnd_iter = rnd_list.begin();
       advance(rnd_iter, rnd_ptr);
       
       
       // Si copia l'elemento. 
       train_set[i] = data_set[*rnd_iter];
//        cout<<endl;
//        for (int j=0; j < give_features_num(); ++j)
// 	  cout<<train_set[i].vector[j]<<" ";
//        cout<<" "<<train_set[i].cluster;
	  
 
       
       // * Si cancella dalla lista di inizializzazione l'elemento appena inserito.
       rnd_list.erase(rnd_iter);       
    } 
    
            
    // COSTRUZIONE TEST SET: i restanti elementi si copiano nel test sets
    
    for(i=0, rnd_iter = rnd_list.begin(); i < test_num; ++i, rnd_iter++)
       test_set[i] = data_set[*rnd_iter];
    
    // Si Cancella la lista
    rnd_list.clear();   
    
    // Si calcolano i range del train sets
    comp_train_ranges();
    comp_dist_train();
    
    return;
  }


  /*
  ----------------- procedura load_test_set -------------------------------
  *** Scritta il: 19/12/03
  Costruisce dinamicamente l'array che deve contenere il test set e lo ca-
  rica dal file.
  *** Ultima modifica:
  */ 

  void Data::load_test_set()
  {
     int i,j, trash, tmp_features, index;
     ifstream in_stream; 
     
     
     

     // Si costruisce il vettore che deve contenere i data item.     
     test_set = new data_item[test_num];

       
      // Si apre il file che contiene il train set
       in_stream.open(test_file_name);
                      
     // Si controlla se il file e' stato aperto correttamente.
     if (!in_stream)
       abort_message("impossibile aprire il file: \"%s\" \n\
       per la lettura del test set!", test_file_name);
     
     /* Si controlla se bisogna caricare il formato di dati speciale o 
        quello standard. */
     if (special_format)
       load_data_set(&in_stream, test_set, test_num);
     else load_data_set2(&in_stream, test_set, test_num); 
     
     
     /* Ciclo principale per la memorizzazione del numero di items specifi-
        cato dal parametro items_num.   
     for (i=0; i < test_num; ++i)
     {
        // *** Inizializzazione dell'i-esimo item del data set. ***
        test_set[i].cluster = -1;
      
        for (j=0; j < features_num; j++)
	       test_set[i].vector[j]= ZERO_VALUE;

        // *** Memorizzazione dei dati relativi all'i-esimo item. ***
        
        // Si evita il primo elemento della riga.
         in_stream>>trash;  
        
        // Si memorizza il cluster vero dell'item.
         in_stream>>test_set[i].cluster;   
        
        // Si controlla se sono caratteri.
        if (char_format)
          ++test_set[i].cluster; // prova VALE SOLO PER I CARATTERI !!!! 
        
        // Si memorizza il numero di feaures presenti sulla riga.
         in_stream>>tmp_features;  
    //   cout<<endl<<i+1<<" "<<test_set[i].cluster<<" "; 
   //       for (j=0; j < 6; ++j)
     //        in_stream>>test_set[i].vector[j]; // prova
        // Memorizzazione delle features
        for (j=0; j < tmp_features; ++j) 
        { 
           // Si memorizza l'indice della feature.
           in_stream>>index;            
            
           // Si controlla se l'indice e' valido.
           if ((index >= 0) && (index < MAX_FEATURES))
             in_stream>>test_set[i].vector[index];    
      //       cout<<j<<":"<<test_set[i].vector[index]<<" ";         
          // else abort_message("ATTENZIONE! Il file %s contiene una features\
          // non valida alla riga %d %d", train_file_name, i, index);               
        }
   //     in_stream>>test_set[i].cluster;  // prova
        
      /*  cout<<endl<<i<<" "<<test_set[i].cluster<<" ";
        for (j=0; j < 6; ++j)
             cout<<test_set[i].vector[j]<<" ";  
     }  */
     
     // Si calcolano i ranges delle features.
     comp_test_ranges();
    

     return;
  }
 /*
  ----------------- procedura load_data_set -------------------------------
  *** Scritta il: 19/12/03
  Carica nell'array passato come secondo parametro il data set presente nel 
  file passato come primo parametro. Il terzo parametro specifica il numero 
  di item da caricare.
  *** Ultima modifica:
  */ 

  void Data::load_data_set(ifstream *in_stream, data_item *data_set, 
                           int item_num)
  {
     int i,j, trash, tmp_features, index;      


     /* Ciclo principale per la memorizzazione del numero di items specifi-
        cato dal parametro items_num. */
     for (i=0; i < item_num; ++i)
     {
        // *** Inizializzazione dell'i-esimo item del data set. ***
        data_set[i].cluster = -1;
      
        for (j=0; j < features_num; j++)
	       data_set[i].vector[j]= ZERO_VALUE;

        // *** Memorizzazione dei dati relativi all'i-esimo item. ***
        
        // Si evita il primo elemento della riga.
        *in_stream>>trash;  
        
        // Si memorizza il cluster vero dell'item.
        *in_stream>>data_set[i].cluster;   
        if (char_format)
          ++data_set[i].cluster; // prova VALE SOLO PER I CARATTERI !!!! 
        
        
        // Si memorizza il numero di feaures presenti sulla riga.
         *in_stream>>tmp_features;  
         
        // Memorizzazione delle features
        for (j=0; j < tmp_features; ++j) 
        { 
           // Si memorizza l'indice della feature.
           *in_stream>>index;            
            
           // Si controlla se l'indice e' valido.
           if ((index >= 0) && (index < MAX_FEATURES))
             *in_stream>>data_set[i].vector[index];    
        }    
     }   

     return;
  }

  /*
  ----------------- procedura load_data_set2 ------------------------------
  *** Scritta il: 19/12/03
  Carica nell'array passato come secondo parametro il data set presente nel 
  file passato come primo parametro. Il terzo parametro specifica il numero 
  di item da caricare.
  ATTENZIONE!: Questa procedura si differenzia dalla precedente dal formato 
  di memorizzazione dei dati. 
  *** Ultima modifica:
  */ 
  void Data::load_data_set2(ifstream *in_stream, data_item *data_set, 
                            int item_num)
  {
     int i,j;      


     /* Ciclo principale per la memorizzazione del numero di items specifi-
        cato dal parametro items_num. */
     for (i=0; i < item_num; ++i)
     {
        // *** Inizializzazione dell'i-esimo item del data set. ***
        data_set[i].cluster = -1;
      
        for (j=0; j < features_num; j++)
	       data_set[i].vector[j]= ZERO_VALUE;

        // *** Memorizzazione dei dati relativi all'i-esimo item. ***               
         
        // Memorizzazione delle features
        for (j=0; j < features_num; ++j) 
           *in_stream>>data_set[i].vector[j];    
                
        // Si memorizza il cluster vero dell'item.
        *in_stream>>data_set[i].cluster;       
     }
     
     
     return;
  }
  
  /*
  ----------------- procedura build_dist_matrix --------------------------
  *** Scritta il: 19/12/03
  Costruisce il maniera DINAMICA la matrice che contiene le distanze fra i
  sample degli elementi del train e test set.  
  *** Ultima modifica:
  */
  void Data::build_dist_matrix()
  {
     int i;
     /* Si costruisce prima il vettore delle righe pari alle dim. del TRAIN
        SET. */ 
     dist_matrix = new dist_row[train_num];
     
     // Si costruiscono le colonne pari alle dim. del TEST SET.
     for (i=0; i < test_num; ++i)
        dist_matrix[i].cols = new double[test_num];
        
     // Si calcolano le distanze...
     comp_dist_matrix();
                                   
     return;
  }
  
  /*
  ----------------- procedura comp_dist_matrix ----------------------------
  *** Scritta il: 19/12/03
  Calola la matrice delle distanze tra train e test set.
  *** Ultima modifica:
  */
  void Data::comp_dist_matrix()
  {
     register int i, j;
     double *tmp_vec;
     
     // Si alloca dinamicamente il vettore temporaneo.
     tmp_vec = new double[features_num];
     
     cout<<endl<<"Calcolo delle distanze degli elementi del train e test";
     cout<<" set...";
     for (i=0; i < train_num; ++i)
     {
        // Si acquisisce l'i-esimo sample del train set.
        data.give_train_item(tmp_vec,i);
        
        /* Si calcolano le distanze tra l'i-esimo sample del train set
           e i sample del test set. */
        for (j=0; j < test_num; ++j)
           dist_matrix[i].cols[j] = comp_test_dist(tmp_vec, j);   
    }
    
    // Si cancella la memoria allocata per il vettore temporaneo.
    delete [] tmp_vec;                                     
    
    cout<<endl<<" Sono state calcolate "<<train_num*test_num<<" distanze."
        <<endl;
    
    return;
  }
  

  /*
  ----------------- procedura comp_train_ranges ---------------------------
  *** Scritta il: 19/12/03
  Calcola i ranges delle features del train set e inizializza il vettore 
  che li contiene.
  Ultima modifica:
  */
  void Data::comp_train_ranges()
  {        
     int i, j, valids;
     double tmp_avg, tmp_dev;
     


     for (i=0; i < features_num; ++i)
        // Si controlla se la feature e' valida.
        if (valid_features[i])          
        {
          // Inizializzazione.
          tmp_avg = 0.0;
          tmp_dev = 0.0;
          
          // Si inizializza il contatore al numero di items validi.
          valids = 0;

          // Calcolo del valore medio dell'i-esima feature.
          for(j=0; j < train_num; ++j)
             // Si controlla se il valore di questo item e' valido. 
             if (train_set[j].vector[i] != NULL_VALUE)
             {
               tmp_avg += train_set[j].vector[i];
                
               // Si incrementa il numero di elementi validi.
               valids++;
             }   
             
          // Si verifica se c'e' almeno un elemento valido.
          if (valids)
            tmp_avg /= valids;
          
          // Si memorizza il valore medio della feature.
          train_ranges[i].avg = tmp_avg;
          
        // Calcolo della deviazione standard.
        for(j=0; j < train_num; ++j)
           // Si controlla se il valore e' valido.
           if (train_set[j].vector[i] != NULL_VALUE)        
             tmp_dev += pow(train_set[j].vector[i] - tmp_avg, 2.0);
        
        // Si controlla valids
        if (valids > 1)
          tmp_dev = sqrt(tmp_dev / (valids - 1));

        /* Si memorizza la deviazione nell'i-esimo elemento del vettore
           ranges. */
        train_ranges[i].dev = NORM_FACTOR * tmp_dev; 
     //   cout<<i<<" "<<tmp_dev<<" ";
        /* Si controlla se la deviazione dell'i-esimo elmento e' uguale a  
           0, in tal caso la feature viene resa non valida. */
        if (train_ranges[i].dev == 0.0)
          valid_features[i] = false;
     }
      
    
     // Si normalizza il train set. 
    // normalize(); 
    //cout<<endl<<"ATTENZIONE!: il test set   e' stato normalizzato!"<<endl;
 
    
       
     return;
  }

/*
  ----------------- procedura comp_test_ranges ----------------------------
  *** Scritta il: 19/12/03
  Calcola i ranges delle features del train set e inizializza il vettore 
  che li contiene.
  Ultima modifica:
  */
  void Data::comp_test_ranges()
  {        
     int i, j, valids;
     double tmp_avg, tmp_dev;
     

     for (i=0; i < features_num; ++i)
        // Si controlla se la feature e' valida.
        //if (valid_features[i])          
        {
          // Inizializzazione.
          tmp_avg = 0.0;
          tmp_dev = 0.0;
          
          // Si inizializza il contatore al numero di items validi.
          valids = 0;

          // Calcolo del valore medio dell'i-esima feature.
          for(j=0; j < test_num; ++j)
             // Si controlla se il valore di questo item e' valido. 
             if (test_set[j].vector[i] != NULL_VALUE)
             {
               tmp_avg += test_set[j].vector[i];
               
               // Si incrementa il numero di elementi validi.
               valids++;
             }   
             
          // Si verifica se c'e' almeno un elemento valido.
          if (valids)
            tmp_avg /= valids;
          
          // Si memorizza il valore medio della feature.
          test_ranges[i].avg = tmp_avg;
          
        // Calcolo della deviazione standard.
        for(j=0; j < test_num; ++j)
           // Si controlla se il valore e' valido.
           if (test_set[j].vector[i] != NULL_VALUE)        
             tmp_dev += pow(test_set[j].vector[i] - tmp_avg, 2.0);
        
        // Si controlla valids
        if (valids > 1)
          tmp_dev = sqrt(tmp_dev / (valids - 1));
       // cout<<i<<" "<<tmp_dev<<" ";
        /* Si memorizza la deviazione nell'i-esimo elemento del vettore
           ranges. */
        test_ranges[i].dev = 2.0 * tmp_dev; 
        
        /* Si controlla se la deviazione dell'i-esimo elemento e' uguale a  
           0, in tal caso la feature viene resa non valida. */
       // if (ranges[i].dev == 0.0)
        //  valid_features[i] = false;
     }
      
    
     // Si normalizza il train set. 
   //  normalize(); 
   //cout<<endl<<"ATTENZIONE!: il test set  e' stato normalizzato!"<<endl;
 
    
       
     return;
  }

  
  /*
  ----------------- procedura normalize -----------------------------------
  *** Scritta il: 19/12/03
  Normalizza i vettori presenti nel train set.
  Ultima modifica:
  */ 
  void Data::normalize()
  {        
     int i, j;
     register double diff; 
     
     // *********** NORMALIZZAZIONE DEL TRAIN SET *************************  
          
     // Si normalizza l'i-esima feature.
     for (i=0; i < features_num; ++i)
        // Si controlla se la feature e' valida.
        if (valid_features[i])          
        // Si scandisce tutto il train set.        
        for (j=0; j  < train_num; ++j)        
          // Si controlla se il valore di questa feature e' valido.
          if (train_set[j].vector[i] != NULL_VALUE)
          {            
            diff = train_set[j].vector[i] - train_ranges[i].avg;
            
            // Si controlla se il valore è troppo distante da quello medio.
            if (fabs(diff) <  train_ranges[i].dev)
              train_set[j].vector[i] = diff /  train_ranges[i].dev; 
            else if (diff > 0.0)
                   train_set[j].vector[i] = 1.0; 
                 else train_set[j].vector[i] = - 1.0;
          } 
     // ************NORMALIZZAZIONE DEL TEST SET *************************  
          
     // Si controlla prima se il test set e' stato caricato.
     if (test)
       // Si normalizza l'i-esima feature.
       for (i=0; i < features_num; ++i)
          // Si controlla se la feature e' valida.
          if (valid_features[i])          
            // Si scandisce tutto il train set.        
            for (j=0; j  < test_num; ++j)        
               // Si controlla se il valore di questa feature e' valido.
               if (test_set[j].vector[i] != NULL_VALUE)
               {            
                 diff = test_set[j].vector[i] - train_ranges[i].avg;
            
                 // Si controlla se il valore è troppo distante da quello medio.
                 if (fabs(diff) <  train_ranges[i].dev)
                   test_set[j].vector[i] = diff /  train_ranges[i].dev; 
                 else if (diff > 0.0)
                        test_set[j].vector[i] = 1.0; 
                      else test_set[j].vector[i] = -1.0;
               } 
                
     
     return;
  }




  /*
  ----------------- procedura comp_vectors_dist ---------------------------
  *** Scritta il: 19/12/03
  Questa funzione calcola la distanza tra i features vector passati come 
  parametri.  
  */ 
  double Data::comp_vectors_dist (double vector_1[],  double vector_2[])
  {
     int i;
     double tmp_dist;

     tmp_dist = 0.0;
     
       
     /* Si calcola prima la somma delle differenze tra gli elementi dei due
        vettori che rappresentano gli items. */
     for (i=0; i < features_num; ++i)
        // Si considerano solo le features valide.
        if (valid_features[i])
          tmp_dist += pow(fabs(vector_1[i] - vector_2[i]) / 
                               give_train_range(i), dist_type);


     /* Si divide per il numero di elementi del vettore elevato all'espo-
        nente.  */
     tmp_dist /= pow(features_num, dist_type);


     // Si effettua la radice.
     tmp_dist = pow(tmp_dist, 1.0 / dist_type);


     return tmp_dist;
  }
  
  /*
  ----------------- procedura comp_train_dist -----------------------------
  *** Scritta il: 19/12/03
  Questa funzione calcola la distanza tra il vettore passato come parametro 
  e l'item del train set di indice index passaato come parametro. Il terzo 
  parametro specifica una distanza minima di riferimento, da utilizzare per
  terminare i calcoli in anticipo per ridurre la complessita'.  
  */
  double Data::comp_train_dist(double vector[],  int index)
  {
     int i;
     double tmp_dist;

     
     tmp_dist = 0.0;

     /* Si calcola prima la somma delle differenze tra gli elementi dei due
        vettori che rappresentano gli items. */
     for (i=0; i < features_num; ++i)     
        // Si considerano solo le features valide.
        if (valid_features[i])
          /* tmp_dist += pow(fabs(vector[i] - train_set[index].vector[i]), dist_type);/* / 
                          train_ranges[i].dev, dist_type);  prova*/
         
          tmp_dist += fabs(vector[i] - train_set[index].vector[i]); // prova
     /* Si divide per il numero di elementi del vettore elevato all'espo-
        nente. */
    // tmp_dist /= pow(features_num, dist_type);


     // Si effettua la radice.
//     tmp_dist = pow(tmp_dist, 1.0 / dist_type);


     return tmp_dist;
  }

  
  /*
  ----------------- procedura comp_train_dist_fast ------------------------
  *** Scritta il: 19/12/03
  Questa funzione calcola la distanza tra il vettore passato come parametro 
  e l'item del train set di indice index passato come parametro, in maniera
  tale da ridurre la complessita' computazionale. Il terzo parametro speci-
  fica una distanza minima di riferimento, da utilizzare per terminare i 
  calcoli in anticipo.  
  */ 
  double Data::comp_train_dist_fast(double vector[],  int index, 
                                     double min_dist)                                      
  {
     int i;
     double tmp_dist, tmp_dist2;

     
     tmp_dist = 0.0; 
 
     /* Si calcola prima la somma delle differenze tra gli elementi dei due
        vettori che rappresentano gli items. */
     for (i=0; i < features_num; ++i)
     {
        // Si considerano solo le features valide.
        if (valid_features[i])
          //tmp_dist += pow(fabs(vector[i] - train_set[index].vector[i]) / 
            //              train_ranges[i].dev, dist_type);
        {  
          tmp_dist +=   fabs(vector[i] - train_set[index].vector[i]) / 
                             train_ranges[i].dev; 
          // tmp_dist2 *= tmp_dist2;
          // tmp_dist += tmp_dist2;                
           
        }
        /* Si controlla se la distanza temporanea calcolata e' maggiore di 
           quella minima passata come parametro, in tal caso e' inutile pro-
           seguire. */ 
        if (tmp_dist > min_dist)        
          return 1000.0;
                
     }    

         
     /* Si divide per il numero di elementi del vettore elevato all'espo-
        nente. */
    // tmp_dist /= pow(features_num, dist_type);


     // Si effettua la radice.
//     tmp_dist = pow(tmp_dist, 1.0 / dist_type);


     return tmp_dist;
  }
 
  /*
  ----------------- procedura comp_test_dist ------------------------------
  *** Scritta il: 19/12/03
  Questa funzione calcola la distanza tra il vettore passato come parametro 
  e l'item del test set di indice index passato come parametro. 
  */
  double Data::comp_test_dist (double vector[],  int index)
  {
     int i;
     double tmp_dist;

     tmp_dist = 0.0;


     /* Si calcola prima la somma delle differenze tra gli elementi dei due
        vettori che rappresentano gli items. */
     for (i=0; i < features_num; ++i)
        // Si considerano solo le features valide.
//        if (test_ranges[i].dev > 0.0) 
        if (valid_features[i])
        {  
          tmp_dist +=   fabs(vector[i] - test_set[index].vector[i]);/*  / 
                             train_ranges[i].dev; prova */
          // tmp_dist2 *= tmp_dist2;
          // tmp_dist += tmp_dist2;                
           
        }
         // tmp_dist += pow(fabs(vector[i] - test_set[index].vector[i]) / 
           //               test_ranges[i].dev, dist_type);


     /* Si divide per il numero di elementi del vettore elevato all'espo-
        nente. */
  //   tmp_dist /= pow(features_num, dist_type);  


     // Si effettua la radice.
   //  tmp_dist = pow(tmp_dist, 1.0 / dist_type);  


     return tmp_dist;
  }
  
  /*
  ----------------- procedura give_train_item -----------------------------
  *** Scritta il: 19/12/03
  Restituisce la classe di appartenenza dell'item del train set di indice 
  index. 
  */
  int Data::give_train_item(int index)
  {
     
     return train_set[index].cluster;
  }
  
  /*
  ----------------- procedura give_test_item -----------------------------
  *** Scritta il: 19/12/03
  Restituisce la classe di appartenenza dell'item del test set di indice 
  index. 
  */
  int Data::give_test_item(int index)
  {
     
     return test_set[index].cluster;
  }
  
  /*
  ----------------- procedura give_k_fold ---------------------------------
  *** Scritta il: 19/12/03
  Restituisce il valore di k della fold validation utilizzata. 
  index. 
  */
  int Data::give_k_value()
  {
     
     return k_value;
  }
 
  /*
  ----------------- procedura get_no_features -----------------------------
  *** Scritta il: 19/12/03
  Questa procedura acquisisce dalla linea passata come parametro le featu-
  res non valide. 
  */
  void Data::get_no_features(char *line)
  {
  
     char *line_ptr;
     int tmp;
     
     
     
     // Inizializzazione.
     line_ptr = line;
     
     while(*line_ptr != '\0')
     {
        tmp = atoi(line_ptr);
        
        // Si controlla se il numero di feature acquisito e' valido.
        if ((tmp < 0) || (tmp > MAX_FEATURES))
          abort_message("ERRORE! \n il file %s contiene un numero di \
          feature non valido!");
        else valid_features[tmp] = false;
        
        /* Questo ciclo serve a saltare il carattere ',' che separa
	       le probabilita'. */
	    while((*line_ptr++ != ',') && (*line_ptr != '\0'))
     	  ;
     }
     
     
     return;
}  


     

  /**********************************************************************
          Definizione delle procedure della classe CLUSTER
  ************************************************************************/

   /*
  ----------------- procedura Cluster ----------------------------------
  *** Scritta il: 19/12/03
  E' la procedura costruttrice della classe. E' vuota, serve solo per allo-
  care un oggetto della classe.
  *** Ultima modifica:
  */
  Cluster::Cluster()
  {
     return;
  }


  /*
  ----------------- procedura Cluster ----------------------------- -------
  *** Scritta il: 19/12/03
  E' la procedura costruttrice della classe. Memorizza il numero del clus-
  ter.
  *** Ultima modifica:
  */
  Cluster::Cluster(int position)
  {
     number = position;
     label = -1;
     
     return;
  }
  
//  /*
//  ----------------- procedura update_clustering ---------------------------
//  *** Scritta il: 19/12/03
//  Aggiorna il clustering passato come parametro aggiungendovi gli items as-
//  segnati al cluster. 
//  *** Ultima modifica:
//  */ 
//  void Cluster::update_clustering(bool *clustering)
//  {
//     int i;
//     
//     
//     for (i=0; i < data.give_train_num(); ++i)
//        if (assignaments[i])
//          clustering[i] = true; 
//  }
  
  /*
  ----------------- procedura update_clustering ---------------------------
  *** Scritta il: 19/12/03
  Aggiorna il clustering passato come parametro aggiungendovi gli items as-
  segnati al cluster. 
  *** Ultima modifica:
  */ 
//  float Cluster::comp_clustering_dist(bool *clustering)
//  {     
//     int i, tmp_dist;
//     
//     // Inizializzazione
//     tmp_dist = 0;
//     
//     // La distanza calcolata tra i due vettori e' quella di Hamming.
//     for (i=0; i < data.give_train_num(); ++i)
//        if (assignaments[i]!= clustering[i])
//          ++tmp_dist;
//          
//     return (float) tmp_dist;     
//  }
//

  /*
  ----------------- procedura comp_centroid -------------------------------
  *** Scritta il: 19/12/03
  Calcola il centroide degli items assegnati al cluster che hanno la stessa
  label  del cluster. Calcola anche la copertura ottenuta. 
  *** Ultima modifica:
  */
//  void Cluster::comp_centroid(memo_item clustering[])
//  {
//     double tmp_vector[MAX_FEATURES], tmp_vector2[MAX_FEATURES];
//     int cover_num, i, j;
//
//     // Inizializzazione.
//     cover_num = 0;
//
//     for (i=0; i < data.give_features_num();  ++i)
//        tmp_vector[i] = 0.0;
// 
//     /* Si trovano gli items del Data set che sono stati assegnati al clus-
//        ter. */  
//     for (i=0; i < data.give_train_num(); ++i)
//        if (clustering[i].cluster == number)
//          // Si controlla se l'item ha la stessa label del cluster.
//          if (data.give_train_item(i) - 1 == label)
//          {   
//            // Si copia l'item richiesto.
//            data.give_train_item(tmp_vector2, i);
//            
//            /* Tutti gli elementi del vettore che rappresenta l'item trova-
//               to vengono sommati in un vettore temporaneo.  */
//            for (j=0; j < data.give_features_num(); ++j)
//               tmp_vector[j] +=tmp_vector2[j];                 
//          
//            ++cover_num;
//          }
//          /* Si incrementa solo la variabile che memorizza il numero di it-
//             ems coperti dal cluster. */ 
//         // else ++cover_num; 
//        
//        
//     
//     /* Adesso si calcola il centroide vero e proprio, dividendo gli ele-
//        menti del vettore temporaneo  per il numero di items assegnati al
//        cluster per matching. Si controlla prima se il cluster metcha alme-
//        no un item.  */ 
//     if (cover_num > 0)
//       for (j=0; j < data.give_features_num(); ++j)       
//          centroid[j] = tmp_vector[j] / cover_num;
//     else for (j=0; j < data.give_features_num(); ++j)
//             centroid[j] = -1.0;
//
//     // Si calcola la percentuale di copertura ottenuta per matching.
//     cover = (double) cover_num;
//
//     return;
//  }
//  
////  /*
//  ----------------- procedura comp_centroids ------------------------------
//  *** Scritta il: 23/06/06
//  Calcola i centroidi degli items della stessa classe assegnati al cluster.    
//  *** Ultima modifica:
//  */
//  void Cluster::comp_centroids(memo_item clustering[])
//  {
//     double tmp_vectors[MAX_CLASSES][MAX_FEATURES], 
//            tmp_vector[MAX_FEATURES];
//     int i, j, cl;
//
//     //********************** Inizializzazione ****************************
//     
//     // Si inizializzano le coperture.
//     for (cl=0; cl < data.give_classes_num(); ++cl)
//     cover_nums[cl] = 0;
//
//     // Si inizializzano i vettori temporanei.  
//     for (cl=0; cl < data.give_classes_num();  ++cl)
//        for (j=0; j  < data.give_features_num(); ++j)
//           tmp_vectors[cl][j] = 0.0;
// 
//     //**************  Calcolo dei centroidi  *****************************
//     
//     /* Si trovano gli items del Data set che sono stati assegnati al clus-
//        ter. */  
//     for (i=0; i < data.give_train_num(); ++i)
//        if (clustering[i].cluster == number)
//        {
//          // Si memorizza la classe effettiva dell'item.   
//          cl = data.give_train_item(i) - 1;
//          
//          // Si copia l'item richiesto.
//          data.give_train_item(tmp_vector, i);
//          
//          /* Il vettore appena copiato viene sommato in un vettore tempora-
//             neo. */
//          for (j=0; j < data.give_features_num(); ++j)
//               tmp_vectors[cl][j] +=tmp_vector[j];
//          
//          /* Si aggiorna la situazione relativa al numero di items di quel-
//             la classe che sono stati assegnati. */
//          cover_nums[cl]++;              
//        
//        } 
//    
//      
//     /* Adesso si calcolano i centroidi, dividendo gli elementi dei vettori
//       temporanei  per il numero di items della stessa classe. */ 
//     for (cl=0; cl < data.give_classes_num(); ++cl)
//        if (cover_nums[cl] > 0)
//          for (j=0; j < data.give_features_num(); ++j)       
//             centroids[cl][j] = tmp_vectors[cl][j] / cover_nums[cl];
//        else for (j=0; j < data.give_features_num(); ++j)
//             centroids[cl][j] = -1.0;      
//
//      
//     return;
//  }
//
//
//   
//
//  /*
//  ----------------- procedura comp_omogeneity -----------------------------
//  *** Scritta il: 19/12/03
//  /* Calcola l'omogeneit� del cluster.
//  *** Ultima modifica:
//  */
//  float Cluster::comp_omogeneity(memo_item clustering[])
//  {
//     int i;
//     double tmp_dist;
//
//     tmp_dist = 0.0;
//
//     // Si controlla se il cluster copre almeno un items.
//     if (cover == 0.0)
//       return  omogeneity = 0.0;
//        
//     /* Si trovano gli items del Data set che sono stati assegnati al clu-
//        ster e si sommano le distanze tra gli items assegnati al cluster e
//        il centroide totale. */
//     for (i=0; i < data.give_train_num(); ++i)
//        if (clustering[i].cluster == number)
//          tmp_dist += pow(data.comp_train_dist(centroid, i), 
//                          data.give_dist_type());
//
//
//     /* L'omogeneit� si ottiene dividendo la distanza totale appena calco-
//        lata per il numero di items assegnati al cluster. Il valore appena
//        calcolato viene restutuito come valore. */
//     return omogeneity = - (tmp_dist / cover);     
//  }
//
//
//  
//
//  
  /*
  ----------------- Inseritore della classe Cluster -----------------------
  *** Scritta il: 19/12/03
  E' l'inseritore della classe Cluster. Stampa nel file passato come para-
  metro tutti i dati del cluster. Il primo parametro e' il puntatore al fi-
  le in cui stampare. Il secondo, invece, indica se stampare nel file anche
  gli items del cluster.
  *** Ultima modifica:
  */
  ostream &operator<<(ostream &stream, Cluster clust)
  {
     int i;

     //******* Si stampano gli attributi fondamentali del cluster. ******
     

     // Percentuali di copertura     
     stream<<"\nCopertura: "<<clust.cover;

     // Si stampano gli attributi di omogeneita' ed iop
    // stream<<"\nOmogeneita': "<<clust.omogeneity;
 

     // Si stampano i centroidi.
     stream<<"\nCentroide: \n";
     for (i=0; i < data.give_features_num(); ++i)
        stream<<" "<<clust.centroid[i];
      
     return stream;
  }



